/*!
    \file    dmx512_receiver.h
    \brief   DMX512接收器驱动头文件

    \version 2025-01-20, V1.0.0, DMX512接收器驱动 for GD32C231C
*/

#ifndef DMX512_RECEIVER_H
#define DMX512_RECEIVER_H

#include "gd32c2x1.h"
#include "dmx512.h"
#include <stdint.h>
#include <stdbool.h>

/* DMX512接收器硬件配置 */
#define DMX512_RX_UART              USART1          /* 使用USART1接收 */
#define DMX512_RX_BAUDRATE          250000          /* DMX512标准波特率 250kbps */
#define DMX512_RX_UART_IRQ          USART1_IRQn     /* USART1中断 */

/* DMX512接收器DMA配置 */
#define DMX512_RX_DMA_CHANNEL       DMA_CH0         /* 使用DMA通道0接收 */
#define DMX512_RX_DMA_REQUEST       DMA_REQUEST_USART1_RX  /* USART1接收DMA请求 */
#define DMX512_RX_DMA_IRQ           DMA_Channel0_IRQn      /* DMA通道0中断 */

/* DMX512接收器GPIO配置 */
#define DMX512_RX_PORT              GPIOA           /* 接收引脚端口 */
#define DMX512_RX_PIN               GPIO_PIN_3      /* 接收引脚 PA3 */
#define DMX512_RX_AF                GPIO_AF_1       /* 复用功能 */

/* DMX512接收器缓冲区配置 */
#define DMX512_RX_BUFFER_SIZE       (DMX512_MAX_CHANNELS + 1)  /* 包含起始码 */
#define DMX512_RX_TIMEOUT_MS        1000            /* 接收超时时间(毫秒) */
#define DMX512_BREAK_MIN_TIME_US    88              /* Break信号最小时间 */
#define DMX512_MAB_MIN_TIME_US      8               /* MAB最小时间 */

/* DMX512接收状态枚举 */
typedef enum {
    DMX512_RX_STATE_IDLE = 0,       /* 空闲状态 */
    DMX512_RX_STATE_BREAK,          /* 检测到Break信号 */
    DMX512_RX_STATE_MAB,            /* 等待Mark After Break */
    DMX512_RX_STATE_START_CODE,     /* 接收起始码 */
    DMX512_RX_STATE_DATA,           /* 接收数据 */
    DMX512_RX_STATE_COMPLETE,       /* 接收完成 */
    DMX512_RX_STATE_ERROR           /* 接收错误 */
} dmx512_rx_state_t;

/* DMX512接收错误类型 */
typedef enum {
    DMX512_RX_ERROR_NONE = 0,       /* 无错误 */
    DMX512_RX_ERROR_FRAMING,        /* 帧错误 */
    DMX512_RX_ERROR_OVERRUN,        /* 溢出错误 */
    DMX512_RX_ERROR_PARITY,         /* 奇偶校验错误 */
    DMX512_RX_ERROR_BREAK_TOO_SHORT,/* Break信号太短 */
    DMX512_RX_ERROR_MAB_TOO_SHORT,  /* MAB信号太短 */
    DMX512_RX_ERROR_INVALID_START_CODE, /* 无效起始码 */
    DMX512_RX_ERROR_TIMEOUT,        /* 接收超时 */
    DMX512_RX_ERROR_DMA             /* DMA错误 */
} dmx512_rx_error_t;

/* DMX512接收统计信息 */
typedef struct {
    uint32_t frames_received;       /* 接收到的帧数 */
    uint32_t frames_valid;          /* 有效帧数 */
    uint32_t frames_error;          /* 错误帧数 */
    uint32_t last_frame_time;       /* 上次接收帧的时间戳 */
    dmx512_rx_error_t last_error;   /* 最后一次错误类型 */
} dmx512_rx_stats_t;

/* DMX512接收器调试事件类型 */
typedef enum {
    DMX512_DEBUG_EVENT_NONE = 0,        /* 无调试事件 */
    DMX512_DEBUG_EVENT_BREAK_DETECTED,  /* 检测到Break信号 */
    DMX512_DEBUG_EVENT_BREAK_COMPLETE,  /* Break信号处理完成 */
    DMX512_DEBUG_EVENT_DATA_START,      /* 数据开始接收 */
    DMX512_DEBUG_EVENT_DMA_COMPLETE,    /* DMA传输完成 */
    DMX512_DEBUG_EVENT_FRAME_COMPLETE,  /* 帧接收完成 */
    DMX512_DEBUG_EVENT_INVALID_START,   /* 无效起始码 */
    DMX512_DEBUG_EVENT_START_VALID,     /* 起始码验证通过 */
    DMX512_DEBUG_EVENT_DMA_ERROR        /* DMA传输错误 */
} dmx512_debug_event_t;

/* DMX512接收器调试信息结构体 */
typedef struct {
    dmx512_debug_event_t event;         /* 调试事件类型 */
    uint8_t data_byte;                  /* 相关数据字节 */
    uint16_t dma_received;              /* DMA接收字节数 */
    uint16_t total_received;            /* 总接收字节数 */
    uint16_t remaining;                 /* DMA剩余字节数 */
    bool pending;                       /* 调试信息待处理标志 */
} dmx512_debug_info_t;

/* DMX512接收器控制结构体 */
typedef struct {
    uint8_t rx_buffer[DMX512_RX_BUFFER_SIZE];   /* 接收缓冲区 */
    uint8_t data_buffer[DMX512_RX_BUFFER_SIZE]; /* 数据缓冲区(双缓冲) */
    uint16_t channel_count;                     /* 接收到的通道数量 */
    uint16_t current_channel;                   /* 当前接收的通道 */
    dmx512_rx_state_t state;                    /* 当前接收状态 */
    dmx512_rx_error_t error;                    /* 当前错误状态 */
    bool frame_ready;                           /* 新帧准备就绪标志 */
    bool receiving;                             /* 正在接收标志 */
    uint32_t break_start_time;                  /* Break开始时间 */
    uint32_t mab_start_time;                    /* MAB开始时间 */
    uint32_t frame_start_time;                  /* 帧开始时间 */
    dmx512_rx_stats_t stats;                    /* 接收统计信息 */
    dmx512_debug_info_t debug_info;             /* 调试信息 */
    
    /* 回调函数指针 */
    void (*frame_received_callback)(uint8_t *data, uint16_t length);  /* 帧接收完成回调 */
    void (*error_callback)(dmx512_rx_error_t error);                  /* 错误回调 */
} dmx512_rx_handle_t;

/* 全局DMX512接收器句柄 */
extern dmx512_rx_handle_t g_dmx512_rx;

/* DMX512接收器驱动函数声明 */

/*!
    \brief      初始化DMX512接收器
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_rx_init(void);

/*!
    \brief      反初始化DMX512接收器
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_rx_deinit(void);

/*!
    \brief      启动DMX512接收
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_rx_start(void);

/*!
    \brief      停止DMX512接收
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_rx_stop(void);

/*!
    \brief      检查是否有新的DMX512帧准备就绪
    \param[in]  none
    \param[out] none
    \retval     true: 有新帧, false: 无新帧
*/
bool dmx512_rx_is_frame_ready(void);

/*!
    \brief      获取接收到的DMX512通道数据
    \param[in]  channel: 通道号 (1-512)
    \param[out] none
    \retval     通道值 (0-255), 如果通道无效返回0
*/
uint8_t dmx512_rx_get_channel(uint16_t channel);

/*!
    \brief      获取接收到的RGB数据
    \param[in]  start_channel: 起始通道号 (1-510)
    \param[out] none
    \retval     RGB颜色值
*/
rgb_color_t dmx512_rx_get_rgb(uint16_t start_channel);

/*!
    \brief      获取多个RGB数据
    \param[in]  start_channel: 起始通道号 (1-510)
    \param[out] colors: RGB颜色数组
    \param[in]  count: 要获取的RGB数量
    \param[out] none
    \retval     实际获取的RGB数量
*/
uint16_t dmx512_rx_get_rgb_array(uint16_t start_channel, rgb_color_t *colors, uint16_t count);

/*!
    \brief      复制接收到的DMX512数据到指定缓冲区
    \param[out] buffer: 目标缓冲区
    \param[in]  buffer_size: 缓冲区大小
    \param[out] none
    \retval     实际复制的字节数
*/
uint16_t dmx512_rx_copy_data(uint8_t *buffer, uint16_t buffer_size);

/*!
    \brief      标记当前帧已处理
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_rx_frame_processed(void);

/*!
    \brief      获取接收统计信息
    \param[out] stats: 统计信息结构体指针
    \param[out] none
    \retval     none
*/
void dmx512_rx_get_stats(dmx512_rx_stats_t *stats);

/*!
    \brief      重置接收统计信息
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_rx_reset_stats(void);

/*!
    \brief      获取当前接收状态
    \param[in]  none
    \param[out] none
    \retval     当前接收状态
*/
dmx512_rx_state_t dmx512_rx_get_state(void);

/*!
    \brief      获取最后一次错误
    \param[in]  none
    \param[out] none
    \retval     错误类型
*/
dmx512_rx_error_t dmx512_rx_get_last_error(void);

/*!
    \brief      设置帧接收完成回调函数
    \param[in]  callback: 回调函数指针
    \param[out] none
    \retval     none
*/
void dmx512_rx_set_frame_callback(void (*callback)(uint8_t *data, uint16_t length));

/*!
    \brief      设置错误回调函数
    \param[in]  callback: 回调函数指针
    \param[out] none
    \retval     none
*/
void dmx512_rx_set_error_callback(void (*callback)(dmx512_rx_error_t error));

/*!  
    \brief      处理调试信息（主循环调用）
    \param[in]  none
    \param[out] none
    \retval     none
    \note       主循环调用此函数处理ISR中产生的调试信息，避免在ISR中执行耗时的printf操作
*/
void dmx512_rx_process_debug_info(void);

/*!  
    \brief      打印完整DMX512数据（主循环调用）
    \param[in]  none
    \param[out] none
    \retval     none
    \note       主循环调用此函数打印完整的DMX512帧数据，避免在ISR中执行耗时操作
*/
void dmx512_rx_print_frame_data(void);

/* 中断处理函数声明 */

/*!
    \brief      DMX512接收器UART中断处理函数
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_rx_uart_irq_handler(void);

/*!
    \brief      DMX512接收器DMA中断处理函数
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_rx_dma_irq_handler(void);

/*!
    \brief      DMX512接收器定时器中断处理函数(用于超时检测)
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_rx_timer_irq_handler(void);

/* 工具函数 */

/*!
    \brief      获取错误描述字符串
    \param[in]  error: 错误类型
    \param[out] none
    \retval     错误描述字符串
*/
const char* dmx512_rx_get_error_string(dmx512_rx_error_t error);

/*!
    \brief      获取状态描述字符串
    \param[in]  state: 状态类型
    \param[out] none
    \retval     状态描述字符串
*/
const char* dmx512_rx_get_state_string(dmx512_rx_state_t state);

#endif /* DMX512_RECEIVER_H */